package com.glidebitmappool.internal;

import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.ImageInfo;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;

import java.util.ArrayDeque;
import java.util.Objects;
import java.util.Queue;

/**
 * 位图工具类
 *
 * @author renpengfei
 * @since 2021-03-12
 */
public class Util {
    private static final int ONE = 1;
    private static final int TWO = 2;
    private static final int FOUR = 4;

    private static HiLogLabel logLabel = new HiLogLabel(HiLog.LOG_APP, 0x001, "Util");

    private Util() {
        // Utility class.
    }

    /**
     * 获取位图字节数
     *
     * @param bitmap
     * @return int
     * @throws IllegalStateException
     */
    public static int getBitmapByteSize(PixelMap bitmap) {
        ImageInfo imageInfo = bitmap.getImageInfo();
        Size size = imageInfo.size;

        /**
         * 对于回收的位图，
         * getAllocationByteCount的返回值无提示地从内部缓冲区大小更改为行字节*高度。
         * 为了避免缓存中的随机不一致，我们在这里断言。
         */
        if (bitmap.isReleased()) {
            throw new IllegalStateException("Cannot obtain size for recycled Bitmap: " + bitmap
                    + "[" + size.width + "x" + size.height + "] " + imageInfo.pixelFormat);
        }

        // Workaround for KitKat initial release NPE in Bitmap, fixed in MR1. See issue #148.
        try {
            return (int) bitmap.getPixelBytesNumber();
        } catch (IllegalArgumentException e) {
            HiLog.error(logLabel, e.getMessage());
        }

        return bitmap.getImageInfo().size.height * bitmap.getBytesNumberPerRow();
    }

    /**
     * 获取位图字节数
     *
     * @param width
     * @param height
     * @param config
     * @return int
     */
    public static int getBitmapByteSize(int width, int height, PixelFormat config) {
        return width * height * getBytesPerPixel(config);
    }

    /**
     * 获取字节像素
     *
     * @param config
     * @return int
     */
    private static int getBytesPerPixel(PixelFormat config) {
        // 通过解码gif的位图在某些环境中具有空的“ config”。
        if (config == null) {
            config = PixelFormat.ARGB_8888;
        }

        int bytesPerPixel;
        switch (config) {
            case ARGB_8888:
                bytesPerPixel = ONE;
                break;
//            case ARGB_4444:
            case RGB_565:
                bytesPerPixel = TWO;
                break;
            default:
                bytesPerPixel = FOUR;
                break;
        }
        return bytesPerPixel;
    }

    /**
     * 创建队列
     *
     * @param size
     * @param <T>
     * @return 返回数组队列
     */
    public static <T> Queue<T> createQueue(int size) {
        return new ArrayDeque<>(size);
    }

    /**
     * 判空
     *
     * @param object
     * @param object1
     * @return boolean
     */
    public static boolean bothNullOrEqual(Object object, Object object1) {
        return Objects.equals(object, object1);
    }

    /**
     * 是否可用位图
     *
     * @param candidate 位图
     * @param targetOptions 属性
     * @return boolean
     */
    public static boolean canUseForInBitmap(
            PixelMap candidate, ImageSource.DecodingOptions targetOptions) {
        /**
         * 从原库  4.4（KitKat）开始，如果新位图的字节大小小于可重复使用的位图候选分配字节数，我们可以重新使用
         */
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        decodingOptions.desiredSize = new Size(1, 1);
        int width = decodingOptions.desiredSize.width / targetOptions.sampleSize;
        int height = decodingOptions.desiredSize.width / targetOptions.sampleSize;
        int byteCount = width * height * getBytesPerPixel(candidate.getImageInfo().pixelFormat);

        try {
            return byteCount <= candidate.getPixelBytesCapacity();
        } catch (IllegalArgumentException e) {
            return byteCount <= candidate.getImageInfo().size.height * candidate.getBytesNumberPerRow();
        }
    }

    /**
     * 计算样本大小
     *
     * @param options
     * @param reqWidth
     * @param reqHeight
     * @return int
     */
    public static int calculateInSampleSize(ImageSource.DecodingOptions options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.desiredSize.height;
        final int width = options.desiredSize.width;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / TWO;
            final int halfWidth = width / TWO;

            /**
             * 计算最大的inSampleSize值，该值为2的幂，并且高度和宽度都大于请求的高度和宽度。
             */
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= TWO;
            }
        }

        return inSampleSize;
    }
}
